%%--------------------------------------------------------------------
%% Author: <vjache>
%% Created: 17.03.2009
%% Description: TODO: Add description to merge_sort
%%--------------------------------------------------------------------
-module(iter_sort_merge).

%%--------------------------------------------------------------------
%% Include files
%%--------------------------------------------------------------------
-include("../include/iter.hrl").
%%--------------------------------------------------------------------
%% Exported Functions
%%--------------------------------------------------------------------
-export([
		 open/1,
		 next/1,
		 close/1,
		 test/2,
		 test/3
		 ]).

%%--------------------------------------------------------------------
%% API Functions
%%--------------------------------------------------------------------

%%--------------------------------------------------------------------
%% Iterator callback functions
%%--------------------------------------------------------------------

open({Iter1,Iter2,PredFun}) ->
	[State1,State2]=[iter:open(I)||I<-[Iter1,Iter2]],
	{State1,State2,PredFun,{nil,nil}}.

next({_State1,_State2,_SortFun,{?EOF,?EOF}}=S) ->
	{S,?EOF};
next({State1,State2,PredFun,{nil,nil}}=_S) ->
	{NewState1,Item1}=iter:next(State1),
	{NewState2,Item2}=iter:next(State2),
	next_(NewState1,NewState2,PredFun,Item1,Item2);
next({State1,State2,PredFun,{nil,Item2}}=_S) ->
	{NewState1,Item1}=iter:next(State1),
	next_(NewState1,State2,PredFun,Item1,Item2);
next({State1,State2,PredFun,{Item1,nil}}=_S) ->
	{NewState2,Item2}=iter:next(State2),
	next_(State1,NewState2,PredFun,Item1,Item2).

close({State1,State2,_SortFun,_L}) ->
	ok=iter:close(State1),
	ok=iter:close(State2),
	ok.

%%--------------------------------------------------------------------
%% Local Functions
%%--------------------------------------------------------------------
next_(State1,State2,PredFun,Item1,Item2) -> %{Buff,Item}
	io:format("pair ~p ~p ~n",[Item1,Item2]),
	{Buff,Item}=case {Item1,Item2} of
		{?EOF,?EOF}=R ->
			{R,?EOF};
		{?EOF,_} ->
			{{?EOF,nil},Item2};
		{_,?EOF} ->
			{{nil,?EOF},Item1};
		_ ->
			case PredFun(Item1,Item2) of
				true ->
					{{nil,Item2},Item1};
				false ->
					{{Item1,nil},Item2}
			end
	end,
	{{State1,State2,PredFun,Buff},Item}.

%%--------------------------------------------------------------------
%% Test Functions
%%--------------------------------------------------------------------
test(L1,L2) ->
	Pred=fun(A,B)->
				 A>B
		 end,
	SL1=lists:sort(Pred,L1),
	SL2=lists:sort(Pred,L2),
	I=iter:from_module(?MODULE, { iter:from_list(SL1),iter:from_list(SL2),Pred }),
	iter:foreach(I,fun(E)->
						   io:format("~p~n",[E])
				 end),
	ok.
test(L1,L2,Pred) ->
	SL1=lists:sort(Pred,L1),
	SL2=lists:sort(Pred,L2),
	I=iter:from_module(?MODULE, { iter:from_list(SL1),iter:from_list(SL2),Pred }),
	iter:foreach(I,fun(E)->
						   io:format("~p~n",[E])
				 end),
	ok.
